package com.star.spring.aop.annotation;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @ClassName AnnotationAspect
 * @Author star
 * @Date 2024/10/18 13:52
 */
@Component // 将该类的对象注入到IoC容器（切面类和实体类都需要加上这个注解）
@Aspect // 注释这是一个切面类
@Slf4j
public class AnnotationAspect {

    private static final String LOG_ANNOTATION = "@annotation(com.star.spring.aop.annotation.Log)";


    @Pointcut(LOG_ANNOTATION)
    public void pointcut() {
        log.info("AnnotationAspect被初始化了");
    }


    // 对标记了@Log注解的方法进行前置通知
    @Before("@annotation(com.star.spring.aop.annotation.Log)")
    public void beforeLog() {
        log.info("前置通知");
    }

    // 获取@Log注解的value值，函数执行的入参和出参
    @After("@annotation(myLog)")
    public void afterLog(JoinPoint joinPoint, Log myLog) {
        // joinPoint参数可以获取方法的基本信息
        // joinPoint.getArgs()获取方法执行时传递的参数
        // joinPoint.getSignature().getName()获取Method对象

        log.info("执行了afterLog");
        log.info("获取方法执行时传递的参数：{}", joinPoint.getArgs());
        log.info("获取方法名：{}", joinPoint.getSignature().getName());

        // 获取注解的value
        String value = myLog.value();
        log.info("获取注解的value：{}", value);
    }


    // 特殊注解@AfterReturning和@AfterThrowing

    // 在下面的afterReturningLog方法中，方法入参的顺序JoinPoint，returning，argNames必须一致
    @AfterReturning(pointcut = "@annotation(myLog)", returning = "result", argNames = "joinPoint,result,myLog")
    public void afterReturningLog(JoinPoint joinPoint, Object result, Log myLog) {
        log.info("执行了afterReturningLog");
        log.info("获取方法执行时传递的参数：{}", Arrays.toString(joinPoint.getArgs()));
        log.info("获取方法名：{}", joinPoint.getSignature().getName());
        log.info("获取注解的value：{}", myLog.value());
        log.info("获取方法的返回值：{}", result);
    }

    @AfterThrowing(value = "pointcut()", throwing = "e")
    public void afterThrowingLog(JoinPoint joinPoint, Throwable e) {

        log.info("执行了afterThrowingLog");
        log.info("获取方法执行时传递的参数：{}", Arrays.toString(joinPoint.getArgs()));
        log.info("获取方法的异常：{}", e);
    }


}
